import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
    /*
        3.3 Imagine a (literal) stack of plates. If the stack gets too high, it might topple.
        Therefore, in real life, we would likely start a new stack when the previous stack exceeds some threshold.
        Implement a data structure SetOf Stacks that mimics this. SetOf Stacks should be composed of several stacks
        and should create a new stack once the previous one exceeds capacity. SetOf Stacks.push() and SetOf Stacks.pop()
        should behave identically to a single stack (that is, popO should return the same values as it would if there were just a single stack).
        FOLLOW UP
        Implement a function popAt(int index) which performs a pop operation on  a specific sub-stack.
    */

public class MultiStack<T> {
    private static final int DEFAULT_STACK_SIZE_LIMIT = 16;
    private final int stackSizeLimit;
    List<StackImpl<T>> listOfStacks = new LinkedList<StackImpl<T>>();
    private int currentStackNum = 0;

    public MultiStack() {
        stackSizeLimit = DEFAULT_STACK_SIZE_LIMIT;
        listOfStacks.add(new StackImpl<T>(stackSizeLimit));
    }

    public MultiStack(int stackSizeLimit) {
        this.stackSizeLimit = stackSizeLimit;
        listOfStacks.add(new StackImpl<T>(stackSizeLimit));
    }

    public T pop() {
        StackImpl<T> currentStack = listOfStacks.get(currentStackNum);
        if (currentStack.isEmpty()) {
            if (currentStackNum == 0) throw new ArrayIndexOutOfBoundsException("The stacks are empty!");
            else {
                listOfStacks.remove(currentStackNum);
                currentStackNum--;
                currentStack = listOfStacks.get(currentStackNum);

            }
        }
        return currentStack.pop();
    }

    public void push(T element) {
        StackImpl<T> currentStack = listOfStacks.get(currentStackNum);
        if (currentStack.pointer == stackSizeLimit) {
            currentStackNum++;
            currentStack = new StackImpl<T>(stackSizeLimit);
            listOfStacks.add(currentStack);
        }
        currentStack.push(element);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("MultiStack{ Number of stacks: " + listOfStacks.size()+ "  ");
        for (StackImpl<T> stack : listOfStacks) {
            sb.append(Arrays.toString(stack.data));
            sb.append(' ');
        }
        sb.append('}');
        return sb.toString();
    }
}
